package com.tgq.demo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.log.Log;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tgq.demo.common.Constants;
import com.tgq.demo.common.EncryptionSymmetric;
import com.tgq.demo.dto.UserDto;
import com.tgq.demo.entity.Menu;
import com.tgq.demo.entity.User;
import com.tgq.demo.exception.ServiceException;
import com.tgq.demo.mapper.RoleMapper;
import com.tgq.demo.mapper.RoleMenuMapper;
import com.tgq.demo.mapper.UserMapper;
import com.tgq.demo.service.IMenuService;
import com.tgq.demo.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tgq.demo.utils.TokenUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 陶国庆
 * @since 2023-01-03
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private static  final  Log LOG = Log.get();

    @Resource
    private RoleMapper roleMapper;
    @Resource
    private RoleMenuMapper roleMenuMapper;
    @Resource
    private IMenuService imenuService;

    @Override
    public UserDto login(UserDto userDto) {
        String password = userDto.getPassword();
        String decrypt = EncryptionSymmetric.Encryption(password);
        userDto.setPassword(decrypt);
        User one = getUserInfo(userDto);
        if (one!=null){
            BeanUtil.copyProperties(one,userDto,true); //拷贝方法
            //设置token
            String token = TokenUtils.genToken(one.getId().toString(), one.getPassword());
            userDto.setToken(token);
            String role = one.getRole();  //ROLE_ADMIN
            //设置用户菜单列表
            List<Menu> roleMenus = getRoleMenus(role);
            userDto.setMenus(roleMenus);
            return userDto;
        }else{
            throw new ServiceException(Constants.CODE_600,"用户名或密码错误");
        }
    }

    @Override
    public User register(UserDto userDto) {
        User one = getUserInfo(userDto);
        if(one==null){
            one = new User();
            BeanUtil.copyProperties(userDto,one,true);
            String password=one.getPassword();
            String encryption = EncryptionSymmetric.Encryption(password);
            one.setPassword(encryption);
            save(one);   //把copy完成后的用户对象储存到数据库
        }else{
            throw new ServiceException(Constants.CODE_600,"用户已存在");
        }
        return null;
    }
    private User getUserInfo(UserDto userDto){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",userDto.getUsername());
        queryWrapper.eq("password",userDto.getPassword());
        User one;
        try {
            one = getOne(queryWrapper);   //从数据库查询用户信息
        }catch (Exception e){
            LOG.error(e);
            throw new ServiceException(Constants.CODE_500,"系统错误");
        }
        return one;
    }

    /**
     * 获取当前角色菜单列表
     * @param roleFlag
     * @return
     */
    private List<Menu> getRoleMenus(String roleFlag){
        /*
             比较复杂的方法  返回roleMenus
         */
        Integer roleId = roleMapper.selectByFlag(roleFlag);
        //当前用户所有菜单id集合
        List<Integer> menuIds = roleMenuMapper.getRoleMenuById(roleId);
        //查出系统所有的菜单
        List<Menu> menus = imenuService.findMenus("");
        //new一个筛选完成后list
        List<Menu> roleMenus =new ArrayList<>();
        //筛选当前角色用户菜单
        for (Menu menu: menus) {
            if (menuIds.contains(menu.getId())){
                roleMenus.add(menu);
            }
            List<Menu> children = menu.getChildren();
            //removeIf 移除children里面不在munuIds中的元素
            children.removeIf(child->!menuIds.contains(child.getId()));
        }

        /*
             简单方法
         */
        List<Menu> menuList = roleMapper.getroleMenus(roleFlag);
        //找到pid为空的数据，pid为空为一级菜单
        List<Menu> parentNode = menuList.stream().filter(menu -> menu.getPid() == null).collect(Collectors.toList());
        //找出一级菜单的子菜单
        for (Menu menu : parentNode) {
            //筛选所有数据中pid=父级id的数据就是二级菜单
            menu.setChildren(menuList.stream().filter(m -> menu.getId().equals(m.getPid())).collect(Collectors.toList()));
        }
        return parentNode;
    }
}
